package com.ryder.petmatediarybackend.module.pet.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ryder.petmatediarybackend.common.exception.BusinessException;
import com.ryder.petmatediarybackend.common.util.RedisKeys;
import com.ryder.petmatediarybackend.module.pet.dto.ApplyTagDTO;
import com.ryder.petmatediarybackend.module.pet.entity.PetTagApplication;
import com.ryder.petmatediarybackend.module.pet.mapper.PetTagApplicationMapper;
import com.ryder.petmatediarybackend.module.pet.service.PetTagApplicationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * 描述: 用户标签申请表（用户申请新增标签，平台管理员审核）(PetTagApplication)表服务实现类
 * 
 * @author Ryder
 * @version 1.0
 * @since 1.0 // 版本号，指明从哪个版本开始
 * 更新日期: 2025-10-30 10:14:16
 */
@Slf4j
@Service("petTagApplicationService")
@RequiredArgsConstructor
public class PetTagApplicationServiceImpl extends ServiceImpl<PetTagApplicationMapper, PetTagApplication> implements PetTagApplicationService {

    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 申请间隔时间（分钟）
     */
    private static final int APPLY_INTERVAL_MINUTES = 5;

    @Override
    public PetTagApplication applyNewTag(Long userId, ApplyTagDTO dto) {
        log.info("[申请新标签] userId={}, tagName={}", userId, dto.getTagName());

        // 1. 检查是否可以申请（5分钟限制）
        if (!canApply(userId)) {
            throw new BusinessException("申请过于频繁，请" + APPLY_INTERVAL_MINUTES + "分钟后再试");
        }

        // 2. 检查标签名称是否已存在待审核的申请
        LambdaQueryWrapper<PetTagApplication> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PetTagApplication::getUserId, userId)
                .eq(PetTagApplication::getTagName, dto.getTagName())
                .eq(PetTagApplication::getAuditStatus, 0); // 待审核
        
        PetTagApplication existingApplication = this.getOne(wrapper);
        if (existingApplication != null) {
            throw new BusinessException("该标签已在审核中，请勿重复申请");
        }

        // 3. 创建申请记录
        PetTagApplication application = new PetTagApplication();
        BeanUtil.copyProperties(dto, application);
        application.setUserId(userId);
        application.setAuditStatus(0); // 待审核

        boolean saved = this.save(application);
        if (!saved) {
            throw new BusinessException("申请提交失败");
        }

        // 4. 申请成功后，设置Redis缓存（5分钟过期）
        String redisKey = RedisKeys.buildTagApplyLimitKey(userId);
        redisTemplate.opsForValue().set(redisKey, LocalDateTime.now().toString(), APPLY_INTERVAL_MINUTES, TimeUnit.MINUTES);
        log.info("[设置申请限制缓存] userId={}, redisKey={}, 过期时间={}分钟", userId, redisKey, APPLY_INTERVAL_MINUTES);

        log.info("[申请新标签成功] applicationId={}, tagName={}", application.getId(), dto.getTagName());
        return application;
    }

    @Override
    public boolean canApply(Long userId) {
        // 从Redis缓存中检查是否存在申请限制
        String redisKey = RedisKeys.buildTagApplyLimitKey(userId);
        Object lastApplyTimeObj = redisTemplate.opsForValue().get(redisKey);
        
        // 如果Redis中没有记录，说明可以申请
        boolean canApply = (lastApplyTimeObj == null);
        
        log.info("[检查申请间隔-Redis] userId={}, redisKey={}, 缓存值={}, 可以申请={}", 
                userId, redisKey, lastApplyTimeObj, canApply);
        
        return canApply;
    }
}
